home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / hdf / unix / hdf3_2r2.lha / HDF3.2r2 / src / hextelt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-28  |  20.8 KB  |  717 lines

  1. /***************************************************************************
  2. *
  3. *
  4. *                         NCSA HDF version 3.2r2
  5. *                            October 30, 1992
  6. *
  7. * NCSA HDF Version 3.2 source code and documentation are in the public
  8. * domain.  Specifically, we give to the public domain all rights for future
  9. * licensing of the source code, all resale rights, and all publishing rights.
  10. *
  11. * We ask, but do not require, that the following message be included in all
  12. * derived works:
  13. *
  14. * Portions developed at the National Center for Supercomputing Applications at
  15. * the University of Illinois at Urbana-Champaign, in collaboration with the
  16. * Information Technology Institute of Singapore.
  17. *
  18. * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
  19. * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
  20. * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
  21. *
  22. ****************************************************************************
  23. */
  24.  
  25. #ifdef RCSID
  26. static char RcsId[] = "@(#)$Revision: 1.4 $";
  27. #endif
  28. /*
  29. $Header: /hdf/hdf/v3.2r2/src/RCS/hextelt.c,v 1.4 1992/10/23 00:14:11 koziol beta koziol $
  30.  
  31. $Log: hextelt.c,v $
  32.  * Revision 1.4  1992/10/23  00:14:11  koziol
  33.  * Changed all DFIstr*() and DFImem*() calls to HDstr*() and HDmem*() calls
  34.  * #ifdef'd out the macros Jason defined for Hopen, Hclose, etc. for Vsets
  35.  * Replaced Vset VFREESPACE and VGETSPACE calls with actual calls to HDfreespace
  36.  * and HDgetspace
  37.  * Added a MS-Windows lower lower for file I/O (which may not be completely working
  38.  *
  39.  * Revision 1.2  1992/10/12  18:11:51  koziol
  40.  * Updated for v3.2r2 release
  41.  *
  42.  * Revision 1.1  1992/08/25  21:40:44  koziol
  43.  * Initial revision
  44.  *
  45. */
  46. /*LINTLIBRARY*/
  47. /*+ hextelt.c
  48.  Routines for external elements, i.e., data elements that reside on
  49.  some other file.
  50. +*/
  51.  
  52. #include "hdf.h"
  53. #include "herr.h"
  54. #include "hfile.h"
  55.  
  56. /* extinfo_t -- external elt information structure */
  57.  
  58. typedef struct {
  59.     int attached;              /* number of access records attached
  60.                                   to this information structure */
  61.     int32 length;              /* length of this element */
  62.     int32 length_file_name;    /* length of the external file name */
  63.     hdf_file_t file_external;      /* external file descriptor */
  64.     char *extern_file_name;    /* name of the external file */
  65. } extinfo_t;
  66.  
  67. /* forward declaration of the functions provided in this module */
  68.  
  69. PRIVATE int32 HXIstaccess
  70.     PROTO((accrec_t *access_rec, int16 access));
  71. PRIVATE int32 HXIstread
  72.     PROTO((accrec_t *rec));
  73. PRIVATE int32 HXIstwrite
  74.     PROTO((accrec_t *rec));
  75. PRIVATE int32 HXIseek
  76.     PROTO((accrec_t *access_rec, int32 offset, int origin));
  77. PRIVATE int32 HXIread
  78.     PROTO((accrec_t *access_rec, int32 length, VOIDP data));
  79. PRIVATE int32 HXIwrite
  80.     PROTO((accrec_t *access_rec, int32 length, VOIDP data));
  81. PRIVATE int32 HXIinquire
  82.     PROTO((accrec_t *access_rec, int32 *pfile_id, uint16 *ptag, uint16 *pref,
  83.             int32 *plength, int32 *poffset,int32 *pposn, int16 *paccess,
  84.             int16 *pspecial));
  85. PRIVATE int32 HXIendaccess
  86.     PROTO((accrec_t *access_rec));
  87.  
  88. /* ext_funcs -- table of the accessing functions of the external
  89.    data element function modules.  The position of each function in
  90.    the table is standard */
  91.  
  92. int32 (*ext_funcs[])() = {
  93.     HXIstread,
  94.     HXIstwrite,
  95.     HXIseek,
  96.     HXIinquire,
  97.     HXIread,
  98.     HXIwrite,
  99.     HXIendaccess,
  100. };
  101.  
  102. /*- HXcreate
  103.  Create a data element in an external file.
  104. -*/
  105. #ifdef PROTOTYPE
  106. int32 HXcreate(int32 file_id, uint16 tag, uint16 ref, char *extern_file_name)
  107. #else
  108. int32 HXcreate(file_id, tag, ref, extern_file_name)
  109.     int32 file_id;             /* file record id */
  110.     uint16 tag, ref;           /* tag/ref of the special data element
  111.                                   to create */
  112.     char *extern_file_name;    /* name of external file to use as
  113.                                   data element */
  114. #endif
  115. {
  116.     char *FUNC="HXcreate";     /* for HERROR */
  117.     filerec_t *file_rec;       /* file record */
  118.     accrec_t *access_rec;      /* access element record */
  119.     int slot;
  120.     dd_t *dd;
  121.     ddblock_t *data_block;     /* dd block ptr to exist data element */
  122.     int32 data_idx;            /* dd list index to existing data element */
  123.     hdf_file_t file_external;      /* external file descriptor */
  124.     extinfo_t *info;           /* special element information */
  125. #ifndef oldspecial
  126.     dd_t *data_dd;             /* dd of existing regular element */
  127.     uint16 special_tag;                /* special version of tag */
  128. #endif
  129.  
  130.     /* clear error stack and validate args */
  131.  
  132.     HEclear();
  133.     file_rec = FID2REC(file_id);
  134.     if (!file_rec || file_rec->refcount == 0 || !extern_file_name
  135. #ifndef oldspecial
  136.        || SPECIALTAG(tag) || (special_tag = MKSPECIALTAG(tag)) == DFTAG_NULL
  137. #endif
  138.        ) {
  139.        HERROR(DFE_ARGS);
  140.        return FAIL;
  141.     }
  142.     if (!(file_rec->access & DFACC_WRITE)) {
  143.        HERROR(DFE_DENIED);
  144.        return FAIL;
  145.     }
  146.  
  147.     /* get a slot in the access records table */
  148.  
  149.     slot = HIget_access_slot();
  150.     if (slot == FAIL) {
  151.        HERROR(DFE_TOOMANY);
  152.        return FAIL;
  153.     }
  154.     access_rec = &access_records[slot];
  155.  
  156.     /* look for existing data element of the same tag/ref */
  157.     if (FAIL != HIlookup_dd(file_rec, tag, ref, &data_block, &data_idx)) {
  158. #ifndef oldspecial
  159.        data_dd = &(data_block->ddlist[data_idx]);
  160.        if (SPECIALTAG(data_dd->tag)) {
  161.  
  162.            /* abort since we cannot convert the data element to an external
  163.               data element */
  164.  
  165.            HERROR(DFE_CANTMOD);
  166.            access_rec->used = FALSE;
  167.            return FAIL;
  168.        }
  169.     } else {
  170.        data_dd = (dd_t *) NULL;
  171. #else
  172.        /* abort since we cannot convert the data element to an external
  173.           data element */
  174.  
  175.        HERROR(DFE_CANTMOD);
  176.        access_rec->used = FALSE;
  177.        return FAIL;
  178. #endif
  179.     }
  180.  
  181.     /* look for empty dd to use */
  182.     if (FAIL == HIlookup_dd(file_rec, DFTAG_NULL, DFREF_WILDCARD,
  183.                          &file_rec->null_block, &file_rec->null_idx)) {
  184.        if (FAIL == HInew_dd_block(file_rec, FILE_NDDS(file_rec), FUNC)) {
  185.            HERROR(DFE_NOFREEDD);
  186.            access_rec->used = FALSE;
  187.            return FAIL;
  188.        } else {
  189.            access_rec->block = file_rec->ddlast;
  190.            access_rec->idx   = 0;
  191.        }
  192.     } else {
  193.       access_rec->block = file_rec->null_block;
  194.       access_rec->idx   = file_rec->null_idx;
  195.     }
  196.     dd = &access_rec->block->ddlist[access_rec->idx];
  197.  
  198.     /* create the external file */
  199.  
  200.     file_external = HI_CREATE(extern_file_name);
  201.     if (OPENERR(file_external)) {
  202.        HERROR(DFE_BADOPEN);
  203.        access_rec->used = FALSE;
  204.        return FAIL;
  205.     }
  206.  
  207.     /* set up the special element information and write it to file */
  208.  
  209.     access_rec->special_info = (VOIDP) HDgetspace((uint32)sizeof(extinfo_t));
  210.     info = (extinfo_t *) access_rec->special_info;
  211.     if (!info) {
  212.        HERROR(DFE_NOSPACE);
  213.        access_rec->used = FALSE;
  214.        return FAIL;
  215.     }
  216.  
  217. #ifndef oldspecial
  218.     if (data_dd) {
  219.        VOIDP buf;              /* temporary buffer */
  220.        buf = (VOIDP)HDgetspace((uint32) data_dd->length);
  221.        if (!buf) {
  222.            HERROR(DFE_NOSPACE);
  223.            HDfreespace(info);
  224.            return FAIL;
  225.        }
  226.        if (HI_SEEK(file_rec->file, data_dd->offset) == FAIL) {
  227.            HERROR(DFE_SEEKERROR);
  228.            HDfreespace(info);
  229.            HDfreespace(buf);
  230.            return FAIL;
  231.        }
  232.        if (HI_READ(file_rec->file, buf, data_dd->length) == FAIL) {
  233.            HERROR(DFE_READERROR);
  234.            HDfreespace(info);
  235.            HDfreespace(buf);
  236.            return FAIL;
  237.        }
  238.        if (HI_SEEK(file_external, 0) == FAIL) {
  239.            HERROR(DFE_SEEKERROR);
  240.            HDfreespace(info);
  241.            HDfreespace(buf);
  242.            return FAIL;
  243.        }
  244.        if (HI_WRITE(file_external, buf, data_dd->length) == FAIL) {
  245.            HERROR(DFE_WRITEERROR);
  246.            HDfreespace(info);
  247.            HDfreespace(buf);
  248.            return FAIL;
  249.        }
  250.        HDfreespace(buf);
  251.        info->length = data_dd->length;
  252.     } else {
  253.        info->length = 0;
  254.     }
  255. #endif
  256.  
  257.     info->attached = 1;
  258.     info->file_external = file_external;
  259.     info->extern_file_name = HDgetspace((uint32)HDstrlen(extern_file_name)+1);
  260.     HIstrncpy(info->extern_file_name, extern_file_name,
  261.           HDstrlen(extern_file_name)+1);
  262.     if (!info->extern_file_name) {
  263.        HERROR(DFE_NOSPACE);
  264.        access_rec->used = FALSE;
  265.        return FAIL;
  266.     }
  267.     info->length_file_name = HDstrlen(extern_file_name);
  268.     {
  269.        uint8 *p = tbuf;
  270.        INT16ENCODE(p, SPECIAL_EXT);
  271.        INT32ENCODE(p, info->length);
  272.        INT32ENCODE(p, info->length_file_name);
  273.        HDstrcpy((char *) p, (char *)extern_file_name);
  274.     }
  275.     if (HI_SEEKEND(file_rec->file) == FAIL) {
  276.        HERROR(DFE_SEEKERROR);
  277.        access_rec->used = FALSE;
  278.        return FAIL;
  279.     }
  280.     dd->offset = HI_TELL(file_rec->file);
  281.     dd->length = 10 + info->length_file_name;
  282.     dd->tag = special_tag;
  283.     dd->ref = ref;
  284.     if (HI_WRITE(file_rec->file, tbuf, dd->length) == FAIL) {
  285.        HERROR(DFE_WRITEERROR);
  286.        access_rec->used = FALSE;
  287.        return FAIL;
  288.     }
  289.  
  290.     if (FAIL == HIupdate_dd(file_rec, access_rec->block,
  291.                            access_rec->idx, FUNC)) {
  292.         access_rec->used = FALSE;
  293.         return FAIL;
  294.     }
  295.  
  296.     /* add new DD to hash table */
  297.     if (FAIL == HIadd_hash_dd(file_rec, dd->tag, dd->ref, access_rec->block,
  298.                            access_rec->idx)) {
  299.         access_rec->used = FALSE;
  300.         return FAIL;
  301.     }
  302.  
  303. #ifndef oldspecial
  304.     if (data_dd) {
  305.        Hdeldd(file_id, data_dd->tag, data_dd->ref);
  306.        HIdel_hash_dd(file_rec, data_dd->tag, data_dd->ref);
  307.     }
  308. #endif
  309.  
  310.     /* update access record and file record */
  311.  
  312.     access_rec->special_func = ext_funcs;
  313.     access_rec->special = SPECIAL_EXT;
  314.     access_rec->posn = 0;
  315.     access_rec->access = DFACC_WRITE;
  316.     access_rec->file_id = file_id;
  317.  
  318.     file_rec->attach++;
  319.     if (ref > file_rec->maxref) file_rec->maxref = ref;
  320.  
  321.     return ASLOT2ID(slot);
  322. }
  323.  
  324. /*- HXIstaccess
  325.  start accessing a data element
  326.  called by HXIstread and HXIstwrite
  327. -*/
  328. #ifdef PROTOTYPE
  329. PRIVATE int32 HXIstaccess(accrec_t *access_rec, int16 access)
  330. #else
  331. PRIVATE int32 HXIstaccess(access_rec, access)
  332.     accrec_t *access_rec;      /* access record */
  333.     int16 access;                        /* access mode */
  334. #endif
  335. {
  336.     char *FUNC="HXIstaccess";  /* for HERROR */
  337.     dd_t *info_dd;             /* dd of the special information element */
  338.     extinfo_t *info;           /* special element information */
  339.     filerec_t *file_rec;       /* file record */
  340.  
  341.     /* get file record and validate */
  342.  
  343.     file_rec = FID2REC(access_rec->file_id);
  344.     if (!file_rec || file_rec->refcount == 0 || !(file_rec->access & access)) {
  345.        HERROR(DFE_ARGS);
  346.        return FAIL;
  347.     }
  348.  
  349.     /* intialize the access record */
  350.  
  351.     access_rec->special = SPECIAL_EXT;
  352.     access_rec->posn = 0;
  353.     access_rec->access = access;
  354.  
  355.     /* get the dd for information */
  356.  
  357.     info_dd = &access_rec->block->ddlist[access_rec->idx];
  358.  
  359.     /* get the special info record */
  360.  
  361.     access_rec->special_info = HIgetspinfo(access_rec,
  362.                                           info_dd->tag, info_dd->ref);
  363.     if (access_rec->special_info) {
  364.  
  365.        /* found it from other access records */
  366.  
  367.        info = (extinfo_t *)access_rec->special_info;
  368.        info->attached++;
  369.  
  370.     } else {
  371.  
  372.        /* look for information in the file */
  373.  
  374.        if (HI_SEEK(file_rec->file, info_dd->offset+2) == FAIL) {
  375.            HERROR(DFE_SEEKERROR);
  376.            access_rec->used = FALSE;
  377.            return FAIL;
  378.        }
  379.        if (HI_READ(file_rec->file, tbuf, 8) == FAIL) {
  380.            HERROR(DFE_READERROR);
  381.            access_rec->used = FALSE;
  382.            return FAIL;
  383.        }
  384.        access_rec->special_info = (VOIDP) HDgetspace((uint32)sizeof(extinfo_t));
  385.        info = (extinfo_t *) access_rec->special_info;
  386.        if (!info) {
  387.            HERROR(DFE_NOSPACE);
  388.            access_rec->used = FALSE;
  389.            return FAIL;
  390.        }
  391.        {
  392.            uint8 *p = tbuf;
  393.            INT32DECODE(p, info->length);
  394.            INT32DECODE(p, info->length_file_name);
  395.        }
  396.        info->extern_file_name = (char *)HDgetspace((uint32)
  397.                                                info->length_file_name + 1);
  398.        if (!info->extern_file_name) {
  399.            HERROR(DFE_NOSPACE);
  400.            access_rec->used = FALSE;
  401.            return FAIL;
  402.        }
  403.        if (HI_READ(file_rec->file, info->extern_file_name,
  404.                   info->length_file_name) == FAIL) {
  405.            HERROR(DFE_READERROR);
  406.            access_rec->used = FALSE;
  407.            return FAIL;
  408.        }
  409.        info->extern_file_name[info->length_file_name] = '\0';
  410.        info->file_external = HI_OPEN(info->extern_file_name, access);
  411.        if (OPENERR(info->file_external)) {
  412.            HERROR(DFE_BADOPEN);
  413.            access_rec->used = FALSE;
  414.            return FAIL;
  415.        }
  416.        info->attached = 1;
  417.     }
  418.  
  419.     file_rec->attach++;
  420.  
  421.     return ASLOT2ID(access_rec-access_records);
  422. }
  423.  
  424. /*- HXIstread
  425.  start reading an external data element
  426. -*/
  427. #ifdef PROTOTYPE
  428. PRIVATE int32 HXIstread(accrec_t *rec)
  429. #else
  430. PRIVATE int32 HXIstread(rec)
  431.     accrec_t *rec;
  432. #endif
  433. {
  434.     return HXIstaccess(rec, DFACC_READ);
  435. }
  436.  
  437. /*- HXIstwrite
  438.  start writing an external data element
  439. -*/
  440. #ifdef PROTOTYPE
  441. PRIVATE int32 HXIstwrite(accrec_t *rec)
  442. #else
  443. PRIVATE int32 HXIstwrite(rec)
  444.     accrec_t *rec;
  445. #endif
  446. {
  447.     return HXIstaccess(rec, DFACC_WRITE);
  448. }
  449.  
  450. /*- HXIseek
  451.  seek to offset with the data element
  452. -*/
  453. #ifdef PROTOTYPE
  454. PRIVATE int32 HXIseek(accrec_t *access_rec, int32 offset, int origin)
  455. #else
  456. PRIVATE int32 HXIseek(access_rec, offset, origin)
  457.     accrec_t *access_rec;
  458.     int32 offset;
  459.     int origin;
  460. #endif
  461. {
  462.     char *FUNC="HXIseek";      /* for HERROR */
  463.  
  464.     /* Adjust offset according to origin.
  465.        there is no upper bound to posn */
  466.  
  467.     if (origin == DF_CURRENT) offset += access_rec->posn;
  468.     if (origin == DF_END)
  469.        offset += ((extinfo_t *)(access_rec->special_info))->length;
  470.     if (offset < 0) {
  471.        HERROR(DFE_RANGE);
  472.        return FAIL;
  473.     }
  474.  
  475.     /* set the offset */
  476.  
  477.     access_rec->posn = offset;
  478.     return SUCCEED;
  479. }
  480.  
  481. /*- HXIread
  482.  read in a portion of data from the external element
  483. -*/
  484. #ifdef PROTOTYPE
  485. PRIVATE int32 HXIread(accrec_t *access_rec, int32 length, VOIDP data)
  486. #else
  487. PRIVATE int32 HXIread(access_rec, length, data)
  488.     accrec_t *access_rec;      /* access record */
  489.     int32 length;              /* length of data to read in */
  490.     VOIDP data;                        /* data buffer */
  491. #endif
  492. {
  493.     char *FUNC="HXIread";      /* for HERROR */
  494.     extinfo_t *info =          /* information on the special element */
  495.        (extinfo_t *)access_rec->special_info;
  496.  
  497.     /* validate length */
  498.     if (length < 0) {
  499.        HERROR(DFE_RANGE);
  500.        return FAIL;
  501.     }
  502.  
  503.     /* adjust length if it falls off the end of the element */
  504.  
  505.  
  506.     if (length == 0) length = info->length - access_rec->posn;
  507.     else
  508.         if (length < 0 || access_rec->posn + length > info->length) {
  509.            HERROR(DFE_RANGE);
  510.            return FAIL;
  511.         }
  512.  
  513.     /* read it in from the file */
  514.  
  515.     if (HI_SEEK(info->file_external, access_rec->posn) == FAIL) {
  516.        HERROR(DFE_SEEKERROR);
  517.        return FAIL;
  518.     }
  519.     if (HI_READ(info->file_external, data, length) == FAIL) {
  520.        HERROR(DFE_READERROR);
  521.        return FAIL;
  522.     }
  523.  
  524.     /* adjust access position */
  525.  
  526.     access_rec->posn += length;
  527.  
  528.     return length;
  529. }
  530.  
  531. /*- HXIwrite
  532.  write a length of data to the element
  533. -*/
  534. #ifdef PROTOTYPE
  535. PRIVATE int32 HXIwrite(accrec_t *access_rec, int32 length, VOIDP data)
  536. #else
  537. PRIVATE int32 HXIwrite(access_rec, length, data)
  538.     accrec_t *access_rec;      /* access record */
  539.     int32 length;              /* length of data to write */
  540.     VOIDP data;                        /* data buffer */
  541. #endif
  542. {
  543.     char *FUNC="HXIwrite";     /* for HERROR */
  544.     extinfo_t *info =          /* information on the special element */
  545.        (extinfo_t*)(access_rec->special_info);
  546.  
  547.     /* validate length */
  548.  
  549.     if (length < 0) {
  550.        HERROR(DFE_RANGE);
  551.        return FAIL;
  552.     }
  553.  
  554.     /* write the data onto file */
  555.  
  556.     if (HI_SEEK(info->file_external, access_rec->posn) == FAIL) {
  557.        HERROR(DFE_SEEKERROR);
  558.        return FAIL;
  559.     }
  560.     if (HI_WRITE(info->file_external, data, length) == FAIL) {
  561.  
  562.        /* this external file might not be opened with write permission,
  563.           reopen the file and try again */
  564.  
  565.        hdf_file_t f = HI_OPEN(info->extern_file_name, DFACC_WRITE);
  566.        if (OPENERR(f) || HI_SEEK(f, access_rec->posn) == FAIL ||
  567.            HI_WRITE(f, data, length) == FAIL) {
  568.            HERROR(DFE_DENIED);
  569.            HI_CLOSE(f);
  570.            return FAIL;
  571.        }
  572.        HI_CLOSE(info->file_external);
  573.  
  574.        /* if okay, substitute the file descriptor */
  575.  
  576.        info->file_external = f;
  577.     }
  578.  
  579.     /* update access record, and information about special elelemt */
  580.  
  581.     access_rec->posn += length;
  582.     if (access_rec->posn > info->length) {
  583.        uint8 *p =      /* temp buffer ptr */
  584.            tbuf;
  585.        dd_t *info_dd =         /* dd of infromation element */
  586.            &access_rec->block->ddlist[access_rec->idx];
  587.        filerec_t *file_rec =   /* file record */
  588.            FID2REC(access_rec->file_id);
  589.  
  590.        info->length = access_rec->posn;
  591.        INT32ENCODE(p, info->length);
  592.        if (HI_SEEK(file_rec->file, info_dd->offset+2) == FAIL) {
  593.            HERROR(DFE_SEEKERROR);
  594.            return FAIL;
  595.        }
  596.        if (HI_WRITE(file_rec->file, tbuf, 4) == FAIL) {
  597.            HERROR(DFE_WRITEERROR);
  598.            return FAIL;
  599.        }
  600.     }
  601.  
  602.     return length;
  603. }
  604.  
  605. /*- HXIinquire
  606.  inquire information about the access record and data element
  607. -*/
  608. #ifdef PROTOTYPE
  609. PRIVATE int32 HXIinquire(accrec_t *access_rec, int32 *pfile_id, uint16 *ptag,
  610.                         uint16 *pref, int32 *plength, int32 *poffset,
  611.                         int32 *pposn, int16 *paccess, int16 *pspecial)
  612. #else
  613. PRIVATE int32 HXIinquire(access_rec, pfile_id, ptag, pref, plength, poffset,
  614.                         pposn, paccess, pspecial)
  615.      accrec_t *access_rec;     /* access record */
  616.      int32 *pfile_id;          /* ptr to file id, OUT */
  617.      uint16 *ptag;             /* ptr to tag of information, OUT */
  618.      uint16 *pref;             /* ptr to ref of information, OUT */
  619.      int32 *plength;           /* ptr to length of data element, OUT */
  620.      int32 *poffset;           /* ptr to offset of data element, OUT */
  621.      int32 *pposn;             /* ptr to position of access in element, OUT */
  622.      int16 *paccess;           /* ptr to access mode, OUT */
  623.      int16 *pspecial;          /* ptr to special code */
  624. #endif
  625. {
  626.     dd_t *info_dd =            /* dd of special information */
  627.        &(access_rec->block->ddlist[access_rec->idx]);
  628.     extinfo_t *info =          /* special information record */
  629.        (extinfo_t *)access_rec->special_info;
  630.  
  631.     /* fill in the variables if they are present */
  632.  
  633.     if (pfile_id) *pfile_id = access_rec->file_id;
  634.     if (ptag) *ptag = info_dd->tag;
  635.     if (pref) *pref = info_dd->ref;
  636.     if (plength) *plength = info->length;
  637.     if (poffset) *poffset = 0; /* meaningless */
  638.     if (pposn) *pposn = access_rec->posn;
  639.     if (paccess) *paccess = access_rec->access;
  640.     if (pspecial) *pspecial = access_rec->special;
  641.  
  642.     return SUCCEED;
  643. }
  644.  
  645. /* ----------------------------- HXIendaccess ----------------------------- */
  646. /*
  647.   Close the file pointed to by the current AID and free the AID
  648. -*/
  649. #ifdef PROTOTYPE
  650. PRIVATE int32 HXIendaccess(accrec_t *access_rec)
  651. #else
  652. PRIVATE int32 HXIendaccess(access_rec)
  653.     accrec_t *access_rec;      /* access record to dispose of */
  654. #endif
  655. {
  656.     char *FUNC="HXIendaccess"; /* for HERROR */
  657.     filerec_t *file_rec =      /* file record */
  658.        FID2REC(access_rec->file_id);
  659.  
  660.     /* close the file pointed to by this access rec */
  661.     HXIcloseAID(access_rec);
  662.  
  663.     /* validate file record */
  664.  
  665.     if (file_rec == (filerec_t *) NULL || file_rec->refcount == 0) {
  666.        HERROR(DFE_INTERNAL);
  667.        return FAIL;
  668.     }
  669.  
  670.     /* detach from the file */
  671.  
  672.     file_rec->attach--;
  673.  
  674.     /* free the access record */
  675.  
  676.     access_rec->used = FALSE;
  677.  
  678.     return SUCCEED;
  679. }
  680.  
  681. /* ----------------------------- HXIcloseAID ------------------------------ */
  682. /*
  683. close the file currently being pointed to by this AID but do *NOT* 
  684. free the AID.
  685.  
  686. This is called by Hnextread() which reuses an AID to point to
  687. the 'next' object as requested.  If the current object was an
  688. external object, the external file needs to be closed before all
  689. reference to it is lost.
  690. -*/
  691. #ifdef PROTOTYPE
  692. int32 HXIcloseAID(accrec_t *access_rec)
  693. #else
  694. int32 HXIcloseAID(access_rec)
  695. accrec_t *access_rec;
  696. #endif
  697. {
  698.  
  699.     char *FUNC="HXIcloseAID"; /* for HERROR */
  700.     extinfo_t *info =          /* special information record */
  701.        (extinfo_t *)access_rec->special_info;
  702.  
  703.     /* detach the special information record.
  704.        If no more references to that, free the record */
  705.  
  706.     if (--(info->attached) == 0) {
  707.        HI_CLOSE(info->file_external);
  708.        HDfreespace((VOIDP) info->extern_file_name);
  709.        HDfreespace((VOIDP) info);
  710.     }
  711.  
  712.     return SUCCEED;
  713.  
  714.  
  715. } /* HXIcloseAID */
  716.  
  717.